﻿using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JSC.Core;
using JSC.Core.Data;
using JSC.Data.NHibernate;
using JSC.Portal.Entities;
using JSC.Portal.Services;
using NHibernate;
using JSC.Portal.Web.Models;
using System;

namespace JSC.Portal.Web.Controllers
{
    [Authorize(Roles = "Administrator,SiteAdministrator")]
    [HandleError]
    public class SectionsController : ServicedController<ISectionService>
    {
        private IModuleTypeService _moduleTypeService;
        private IDao<Role> _roleDao;

        public SectionsController()
        {
            _moduleTypeService = FacadeFactory.CreateFacade<IModuleTypeService>();
            _roleDao = new CommonDao<Role>();
        }

        public ActionResult Edit(int id)
        {
            Section s = Service.GetById(id, false);
            LoadSelectionLists(s);
            return View(s);
        }

        public ActionResult EditControl(int id)
        {
            Section s = Service.GetById(id, false);
            LoadSelectionLists(s);
            return PartialView(s);
        }

        public ActionResult Create(int id)
        {
            Section s = Service.GetNewSection(id);
            LoadSelectionLists(s);
            return View("Edit", s);
        }

        public ActionResult Delete(int id)
        {
            using (ITransaction trans = NHibernateSession.Current.BeginTransaction())
            {
                Section s = Service.GetById(id, false);
                int pageid = s.Page.Id;
                s.Page.Sections.Remove(s);
                Service.Delete(s);
                trans.Commit();
                return RedirectToAction("Edit", ControllerNames.PORTALPAGES_CONTROLLER, new { id = pageid });
            }
        }

        public ActionResult SaveOrUpdate(int id, string name, string description, ModuleType moduletype, int portalpageid, 
            string placeholder, bool showname, DateTime validfrom, DateTime? validtill, int[] viewAllowedRoles, int[] editAllowedRoles, 
            IList<ModulePropertyValueDTO> moduleproperties)
        {
            using (ITransaction trans = NHibernateSession.Current.BeginTransaction())
            {
                Section s = Service.GetById(id, false, true);
                s.Name = name;
                s.Description = description;
                s.ModuleType = _moduleTypeService.GetById(moduletype.Id, false);
                s.Page = FacadeFactory.CreateFacade<IPortalPageService>().GetById(portalpageid, false);
                s.Placeholder = placeholder;
                s.ShowName = showname;
                s.ValidFrom = validfrom;
                s.ValidTill = validtill;
                SetPermissions(ref s, viewAllowedRoles, editAllowedRoles);
                if (s.IsNew)
                {
                    int max = -1;
                    if (s.Page != null && s.Page.Sections.Count > 0)
                        max = s.Page.Sections.Max(m => m.Position);
                    s.Position = ++max;
                }
                if (moduleproperties != null)
                {
                    s.Settings.Clear();
                    moduleproperties.ForEach(delegate(ModulePropertyValueDTO dto)
                    {
                        ModuleProperty mp = s.ModuleType.ModuleProperties.Single(x => x.Name == dto.Name);
                        SectionModulePropertyValue smpv = new SectionModulePropertyValue() { ModuleProperty = mp, Section = s, Value = dto.Value };
                        s.Settings.Add(smpv);
                    });
                }
                s.SetTrackedData(User.Identity as PortalUser);
                s = Service.SaveOrUpdate(s);
                trans.Commit();
                return RedirectToAction("Edit", new { id = s.Id });
            }
        }

        public ActionResult Move(int id, MoveAction moveAction)
        {
            using (ITransaction trans = NHibernateSession.Current.BeginTransaction())
            {
                Section s = Service.GetById(id, false);
                Service.MoveSection(s, moveAction);
                trans.Commit();
                return RedirectToAction("Edit", new { id = s.Id });
            }
        }

        public ActionResult GetModuleProperties(int id, int moduleTypeId)
        {
            Section s = Service.GetById(id, false, true);
            ModuleType mt = _moduleTypeService.GetById(moduleTypeId, false);

            IList<SectionModulePropertyValue> result = new List<SectionModulePropertyValue>();
            foreach (ModuleProperty mp in mt.ModuleProperties)
            {
                SectionModulePropertyValue smpv = new SectionModulePropertyValue();
                smpv.ModuleProperty = mp;
                smpv.Section = s;
                foreach (SectionModulePropertyValue smpv2 in s.Settings)
                {
                    if (smpv2.ModuleProperty.Id == mp.Id)
                    {
                        smpv.Value = smpv2.Value;
                    }
                }
                result.Add(smpv);
            }           
            
            return PartialView("ModulePropertiesEditControl", result);
        }

        private void SetPermissions(ref Section section, int[] viewAllowedRoles, int[] editAllowedRoles)
        {
            section.SectionPermissions.Clear();
            foreach (Role r in _roleDao.GetAll().OrderByDescending(r => r.Id))
            {
                SectionPermission sp = new SectionPermission();
                sp.Role = r;
                sp.Section = section;
                sp.ViewAllowed = viewAllowedRoles.Contains<int>(r.Id);
                sp.EditAllowed = editAllowedRoles.Contains<int>(r.Id);
                if (sp.ViewAllowed || sp.EditAllowed)
                    section.SectionPermissions.Add(sp);
            }
        }

        private IList<Permission> GetPermissions(Section section)
        {
            IList<Permission> permissions = new List<Permission>();
            var roles = _roleDao.GetAll().OrderByDescending(r => r.Id);
            foreach (Role r in roles)
            {
                SectionPermission sp = new SectionPermission();
                sp.Section = section;
                sp.Role = r;
                if (section != null)
                {
                    foreach (SectionPermission sp2 in section.SectionPermissions)
                    {
                        if (sp.RoleId == sp2.RoleId)
                        {
                            sp.ViewAllowed = sp2.ViewAllowed;
                            sp.EditAllowed = sp2.EditAllowed;
                        }
                    }
                }
                permissions.Add(sp);
            }
            return permissions;
        }

        private void LoadSelectionLists(Section section)
        {
            string path = VirtualPathUtility.Combine(section.Page.Template.Path, section.Page.Template.ControlName);
            path = Server.MapPath(path);
            IList<string> placeholders = FacadeFactory.CreateFacade<IPortalPageService>().GetTemplatePlaceholders(path);

            this.ViewData["Permissions"] = GetPermissions(section);
            this.ViewData["ModuleTypes"] = new SelectList(_moduleTypeService.GetAll(), "Id", "Name", (section.ModuleType == null) ? "" : section.ModuleType.Id.ToString());
            this.ViewData["Placeholders"] = new SelectList(placeholders, section.Placeholder);
        }
    }
}
